/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.asportoonline.integration;

import java.util.ArrayList;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.asportoonline.entities.Locale;
import org.asportoonline.entities.Prodotto;

/**
 * Questa classe implementa i metodi di ProdottoFacade, necessari per interfacciarsi con l'entità Prodotto.
 * 
 * @author fe
 * @see ProdottoFacade
 */
@Stateless
public class ProdottoFacadeImplementation extends AbstractFacade<Prodotto> implements ProdottoFacade {
    @PersistenceContext(unitName = "AsportoOnline-ejbPU")
    private EntityManager em;

    protected EntityManager getEntityManager() {
        return em;
    }

    public ProdottoFacadeImplementation() {
        super(Prodotto.class);
    }
    
    /**
     * Cerca un prodotto in base al nome e al locale a cui è associato.
     * 
     * @param nome_prodotto nome del prodotto
     * @param locale Locale a cui è associato il prodotto
     * @return restituisce il Prodotto, se esiste, altrimenti null.
     * @see Prodotto
     * @see Locale
     */
    public Prodotto findRestaurantProduct(String nome_prodotto, Locale locale) {
        Query query = em.createQuery("select p from Prodotto p where p.nome = :nome and p.locale = :locale");
        query.setParameter("nome", nome_prodotto);
        query.setParameter("locale", locale);
        List<Prodotto> lp = (List<Prodotto>)query.getResultList();
        
        if(lp==null || lp.isEmpty())    return null;
        return (Prodotto)lp.get(0);
    }
    
    /**
     * Cerca tutti i Prodotti di un Locale.
     * 
     * @param locale Locale di cui si vogliono recuperare i prodotti
     * @return restituisce una lista contenente tutti i Prodotti del Locale locale;
     * se il locale non esiste o non ha nessun prodotto associato restituisce null.
     * @see Prodotto
     * @see Locale
     */
    public List<Prodotto> findAllRestaurantProducts(Locale locale) {
        Query query = em.createQuery("select p from Prodotto p where p.locale = :locale order by p.nome");
        query.setParameter("locale", locale);
        List<Prodotto> lp = (List<Prodotto>)query.getResultList();
        
        if(lp==null || lp.isEmpty())    return null;
        return lp;
    }
    

    /**
     * Cerca un Prodotto in base all'ID.
     * 
     * @param id ID del prodotto.
     * @return se l'ID esiste restituisce il Prodotto, altrimenti restituisce null.
     * @see Prodotto
     */
    public Prodotto find(long id) {
        Query query = em.createQuery("select p from Prodotto p where p.idProdotto = :idprod");
        query.setParameter("idprod", id);
        List<Prodotto> lp = (List<Prodotto>)query.getResultList();
        if(lp==null || lp.isEmpty())    return null;
        return (Prodotto)lp.get(0);        
    }
    
    /**
     * Modifica un prodotto esistente.
     * 
     * @param prodotto 
     * @see Prodotto
     */
    @Override
    public void edit(Prodotto prodotto) {
        em.merge(prodotto);
    }

    /**
     * Cerca tutti i locali che offrono almeno un prodotto di una certa categoria.
     * 
     * @param nomeCategoria nome della categoria 
     * @return restituisce il numero dei locali trovati
     */
    public int numberRestaurantsWithProductsCategory(String nomeCategoria) {
        Query query = em.createQuery("select distinct p.locale from Prodotto p where p.categoria.nome = :nome");
        query.setParameter("nome", nomeCategoria);
        List<Prodotto> lp = (List<Prodotto>)query.getResultList();
        if(lp==null || lp.isEmpty())    return 0;
        return lp.size();                
    }

    /**
     * Cerca tutti i locali, di una certa localita, che offrono almeno un prodotto di una certa categoria.
     * 
     * @param nomeCategoria nome della categoria 
     * @return restituisce il numero dei locali trovati
     */
    public int numberRestaurantsInLocalityWithProductsCategory(String nomeCategoria, String locality) {
        Query query = em.createQuery("select distinct p.locale from Prodotto p where p.categoria.nome = :nome and p.locale.indirizzo.citta = :citta");
        query.setParameter("nome", nomeCategoria);
        query.setParameter("citta", locality);
        List<Prodotto> lp = (List<Prodotto>)query.getResultList();
        if(lp==null || lp.isEmpty())    return 0;
        return lp.size();                
    }

    /**
     * Cerca tutti i locali che offrono almeno un prodotto di una certa categoria.
     * 
     * @param nomeCategoria nome della categoria 
     * @return restituisce una lista contenente tutti i locali trovati; se non ne trova restituisce null
     * @see Locale
     */
    public List<Locale> restaurantsWithProductsCategory(String nomeCategoria) {
        Query query = em.createQuery("select distinct p.locale from Prodotto p where p.categoria.nome = :nome");
        query.setParameter("nome", nomeCategoria);
        List<Locale> ll = (List<Locale>)query.getResultList();
        if(ll==null || ll.isEmpty())    return null;
        return ll;
    }

    /**
     * Cerca tutti i nomi delle categorie offerte dai locali di una certa localita.
     * 
     * @param localita  nome della localita
     * @return restituisce una lista contenente i nomi delle categorie offerte dai locali di una certa localita; se non ne trova restituisce null
     * @see Locale
     */
    public List<String> categoriesRestaurantsLocality(String localita) {
        Query query = em.createQuery("select distinct p.categoria.nome from Prodotto p where p.locale.indirizzo.citta = :citta");
        query.setParameter("citta", localita);
        List<String> ll = (List<String>)query.getResultList();
        if(ll==null || ll.isEmpty())    return null;
        return ll;
    }

    /**
     * Cerca tutti i locali, di una certa localita, che offrono almeno un prodotto di una certa categoria.
     * 
     * @param nomeCategoria nome della categoria 
     * @return restituisce una lista contenente tutti i locali trovati; se non ne trova restituisce null
     * @see Locale
     */
    public List<Locale> restaurantsInLocalityWithProductsCategory(String nomeCategoria, String localita) {
        Query query = em.createQuery("select distinct p.locale from Prodotto p where p.categoria.nome = :nome and p.locale.indirizzo.citta = :citta");
        query.setParameter("nome", nomeCategoria);
        query.setParameter("citta", localita);
        List<Locale> ll = (List<Locale>)query.getResultList();
        if(ll==null || ll.isEmpty())    return null;
        return ll;
    }

}
